package pl.easyshop.core.services.user.group;

import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import pl.easyshop.core.model.UserGroupAuthorityModel;
import pl.easyshop.core.model.UserGroupModel;
import pl.easyshop.core.model.UserModel;
import pl.easyshop.core.services.AbstractBaseService;

@Service("userGroupService")
public class UserGroupServiceImpl extends AbstractBaseService implements UserGroupService {

	/** Logger. */
	private final static Logger LOG = Logger.getLogger(UserGroupServiceImpl.class);
	
	@Override
	@Transactional(readOnly=true)
	public UserGroupData getGroup(Long groupId) {
		UserGroupModel groupModel = getDAORegistry().getUserGroupDAO().load(groupId);
		return getDozerMapper().map(groupModel, UserGroupData.class);
	}
	
	@Override
	@Transactional
	public void bindUserToGroup(Long userId, Long groupId) {
		UserModel userModel = getDAORegistry().getUserDAO().findById(userId);
		UserGroupModel groupModel = getDAORegistry().getUserGroupDAO().load(groupId);
		groupModel.addToGroup(userModel);
		getDAORegistry().getUserGroupDAO().update(groupModel);
	}

	@Override
	@Transactional
	public void bindUsersToGroup(List<Long> userIds, Long groupId) {
		UserGroupModel groupModel = getDAORegistry().getUserGroupDAO().load(groupId);
		UserModel userModel = null;
		for (Long userId : userIds) {
			userModel = getDAORegistry().getUserDAO().findById(userId);
			groupModel.addToGroup(userModel);
		}
		getDAORegistry().getUserGroupDAO().update(groupModel);
	}

	@Override
	@Transactional
	public Long createGroup(UserGroupData groupData) {
		UserGroupModel model = getDozerMapper().map(groupData, UserGroupModel.class);
		LOG.debug("New group data model: " + model);
		return getDAORegistry().getUserGroupDAO().save(model);
	}

	@Override
	@Transactional(readOnly=true)
	public List<UserGroupData> getGroups() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	@Transactional(readOnly=true)
	public List<UserGroupData> getGroups(Long userId) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	@Transactional(readOnly=true)
	public List<UserModel> getUsers(Long groupId) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	@Transactional
	public void removeGroup(Long groupId) {
		LOG.info("Invoke removeGroup");
		getDAORegistry().getUserGroupDAO().delete(groupId);
	}

	@Override
	@Transactional
	public void updateGroup(UserGroupData groupData) {
		LOG.info("Invoke updateGroup");
		UserGroupModel model = getDozerMapper().map(groupData, UserGroupModel.class);
		LOG.debug("Update group data model: " + model);
		getDAORegistry().getUserGroupDAO().update(model);
	}

	@Override
	@Transactional
	public void addRoles(Long groupId, Set<String> roles) {
		
		LOG.info("Invoke addRoles for groupid=" + groupId);
		UserGroupModel groupModel = getDAORegistry().getUserGroupDAO().load(groupId);
		Set<UserGroupAuthorityModel> existingRoles = groupModel.getRoles();
		
		if (existingRoles.isEmpty()) {
			UserGroupAuthorityModel authorityModel = null;
			for (String role : roles) {
				authorityModel = new UserGroupAuthorityModel();
				authorityModel.setGroup(groupModel);
				authorityModel.setRole(role);
				groupModel.addRole(authorityModel);
			}
		} else {
			//remove roles
			for (Iterator<UserGroupAuthorityModel> iterator = existingRoles.iterator(); iterator.hasNext();) {
				UserGroupAuthorityModel groupRole = iterator.next();
				if(!roles.contains(groupRole.getRole())) {
					iterator.remove();
				}
			}
			
			for (String role : roles) {
				if(!checkExistingRole(role, existingRoles)) {
					UserGroupAuthorityModel authorityModel = new UserGroupAuthorityModel();
					authorityModel.setGroup(groupModel);
					authorityModel.setRole(role);
					groupModel.addRole(authorityModel);
				}
			}
		}
		
	}
	
	private boolean checkExistingRole(String roleName, Set<UserGroupAuthorityModel> existingRoles) {
		for (Iterator<UserGroupAuthorityModel> iterator = existingRoles.iterator(); iterator.hasNext();) {
			UserGroupAuthorityModel userGroupAuthorityModel = iterator.next();
			if(roleName.equals(userGroupAuthorityModel.getRole())) {
				return true;
			}
		}
		return false;
	}

	
	
}
